module Data where

import Data.IntSet (IntSet)
import List (union)
import qualified Data.IntSet as IS

type Posicion = (Int, Int)
type Libres = [(Posicion, Digitos)]
type Ocupadas = [(Posicion, Int)]
type Sudoku = (Libres,Ocupadas)
type Digitos = IntSet

----------------------------------------------------------------------------------------------------------------------
-------------------------------LIBRES---------------------------------------------------------------------------------------

--Dada una posicion retorna los candidatos de su ambito
candidatosAmbito :: Posicion -> Ocupadas -> [Int]
candidatosAmbito pos ocupadas = [v  | (p,v) <- ocupadas, p <- (ambitoOcupadas pos ocupadas)]

ambitoOcupadas :: Posicion -> Ocupadas -> [Posicion]
ambitoOcupadas (i,j) ocupadas = union filCol reg
	where filCol = [(x,y) | ((x,y),v) <- ocupadas, ((x==i) && (y/=j)) || ((x/=i) && (y==j))];
		  reg = regiones (i,j)

obtenerLibres :: Ocupadas -> Libres -> Libres
obtenerLibres ocupadas libres = map (obtenerCandidatosLibres ocupadas)  libres	  
	
obtenerCandidatosLibres :: Ocupadas -> (Posicion,Digitos) -> (Posicion,Digitos)
obtenerCandidatosLibres ocupadas (p,d) = (p,r)
	where r = IS.difference d (IS.fromList (candidatosAmbito p ocupadas))
		  
--Dado un par retorna los pares que pertenecen a su region
regiones :: (Int,Int) -> [Posicion]
regiones (m,n) = [(p,q) | x <- [0..2], y <- [0..2], let p = ((quot m 3) + x) ,  let q = ((quot n 3) + y), (m/=p) || (n/=q)]

--Para todos los libres, agrega sus candidatos iniciales
 
		  
----------------------------------------------------------------------------------------------------------------------
-------------------------------CANDIDATOS---------------------------------------------------------------------------------------

--Para probar
--candidatos [((0,0),IS.fromList [1,2,3,4]), ((0,1),IS.fromList [2,7,9]), ((0,2),IS.fromList [1])] (0,1)
candidatos :: Libres -> Posicion -> Digitos
candidatos libres pos 
	| dg == [] = IS.empty
	| otherwise = (head dg)
	where  dg = [d | (p,d) <- libres , ((fst p) == (fst pos)) && ((snd p) == (snd pos))]

